package com.minelx.scriptbuilder.script;

import com.minelx.scriptbuilder.script.attribute.value.IAttribute;

import java.util.function.Supplier;

public interface IVariable {

	IVariable NIL = new IVariable() {
		@Override
		public IAttribute value() {
			return IAttribute.nil();
		}

		@Override
		public void assigned(IAttribute as) {
			throw new UnsupportedOperationException("assign " + as + " to an NIL Variable.");
		}
	};

	IAttribute value();

	void assigned(IAttribute as);

	default boolean exists() {
		return value() != null && !value().isNull();
	}

	default boolean isNull() {
		return this == NIL;
	}

	default IVariable dot(String name) {
		return new Variable(this, name);
	}

	static IVariable nil() {
		return NIL;
	}

	static IVariable immediate(IAttribute immediateValue) {
		// FIXME 2021/3/17  wait for me!!!    immediate got no parent and selfName
		// FIXME 2021/3/27  wait for me!!!
		return new IVariable() {
			@Override
			public IAttribute value() {
				return immediateValue;
			}

			@Override
			public void assigned(IAttribute as) {
				throw new RuntimeException("can't do assignment to an immediate value.");
			}
		};
	}

	static IVariable immediate(Supplier<IAttribute> valueSupplier) {
		return new IVariable() {
			@Override
			public IAttribute value() {
				return valueSupplier.get();
			}

			@Override
			public void assigned(IAttribute as) {
				throw new RuntimeException("can't do assignment to an immediate value.");
			}
		};
	}
}
